#include "game.hpp"

#include <boost/foreach.hpp>
#include <thread>

#include "standard.hpp"
#include "util.hpp"

int game::_start_credits = 50;

game::game(std::vector<boost::shared_ptr<rts_client> >& players) :
    _active(true),
    _players(players),
    _current_frame(0)
{
    BOOST_FOREACH(boost::shared_ptr<rts_client> p, _players)
    {
        p->set_receiver(this);
        p->disconnected().connect(boost::bind(&game::player_dc, this, _1));
    }
    initialize_game_state();
}

void game::initialize_game_state()
{
    std::wstringstream player_start_info;
    for(unsigned int i = 0; i < _players.size(); i++)
    {
        player_start_info << static_cast<wchar_t>(_players[i]->index()) << static_cast<wchar_t>(_start_credits) << static_cast<wchar_t>(1-i);
    }

    // send initial state to all clients
    BOOST_FOREACH(boost::shared_ptr<rts_client> p, _players)
    {
        std::wstringstream p_index;
        p_index << static_cast<wchar_t>(game::initial_game_state) << static_cast<wchar_t>(p->index()) << player_start_info.str();
        p->send(p_index.str());
        std::cout << "initial state: " << std::endl;
        BOOST_FOREACH(wchar_t c, p_index.str())
        {
            std::cout << c << ", ";
        }
        std::cout << std::endl;
    }
}

void game::player_dc(boost::shared_ptr<client> c)
{
    // TODO: lock this
    auto it = std::find_if(_players.begin(), _players.end(), [&c] (const boost::shared_ptr<rts_client> p) { return p->index() == c->index(); });
    _players.erase(it, _players.end());
    if(_players.size() == 0) _game_over(boost::static_pointer_cast<game>(shared_from_this()));
}

void game::receive_message(const std::wstring &message, boost::shared_ptr<client> sender)
{
    boost::shared_ptr<rts_client> player = boost::static_pointer_cast<rts_client>(sender);

    switch(message[0])
    {
        case game::orders:
        {
            if(_orders.count(message[1]) == 0)
            {
                _orders[message[1]] = order_map();
            }
            if(_orders[message[1]].count(message[2]) == 0)
            {
                _orders[message[1]][message[2]] = message.substr(2);
            }
            else
            {
                _orders[message[1]][message[2]] += message.substr(2);
            }
            if(_orders[message[1]].size() == _players.size())
            {
                std::wstringstream order;
                order << static_cast<wchar_t>(game::orders) << message[1];
                BOOST_FOREACH(order_map::value_type& o, _orders[message[1]])
                {
                    order << o.second;
                }

                std::cout << "sending message" << std::endl;
                BOOST_FOREACH(wchar_t c, order.str())
                {
                    std::cout << static_cast<int>(c) << ", ";
                }
                std::cout << std::endl;

                BOOST_FOREACH(boost::shared_ptr<rts_client> p, _players)
                {
                    p->send(order.str());
                }
            }
            break;
        }
        case game::chat:
        {
            BOOST_FOREACH(boost::shared_ptr<rts_client> p, _players)
            {
                std::wstringstream message_with_id;
                message_with_id << static_cast<wchar_t>(game::chat) << player->index() << ": " << message.substr(1);
                p->send(message_with_id.str());
            }
            break;
        }
    }
}
